// Object.defineProperty(对象,key,{})
// set  get 

// es6之后 新增的api
// proxy  vue3 IE 8以下  别用
// const proxy = new Proxy(target,); target: 拦截

const target = {
  a:1
};


// const target = [1,2,3];
// Proxy Reflect : 反射 Proxy
// Proxy 每个拦截方法 都会有返回值 此时就可以利用Reflect 和 Proxy一一对应起来
const proxy = new Proxy(target,{
  // 13种拦截
  set(target,key,value,receiver){
    console.log(target,key,value);
    return Reflect.set(target,key,value,receiver);
  },

  has(target,key){
    console.log('has的拦截',key);
    return Reflect.has(target,key);
  },

  deleteProperty(target,p){
    console.log('删除的拦截',p);
    return false;
  }

  // get(target,p,receiver){
  //   console.log(target,p,receiver);// ?
  //   return Reflect.get(target,p,receiver);
  // }

  
});

// 删除
Reflect.deleteProperty(proxy,'a');
// has
Reflect.has(target,'a');// ?
// delete proxy.a;
// console.log(proxy.a);


// 拦截到了数组下标的变化
// proxy[0] = '1';
// proxy.push(20);


// 入参 : 拦截的对象或者数组
const o = {
  a:[1,2],
  c:{
    a:1,
    b:2,
    c:[
      [1,2,{
        d:3
      }]
    ]
  },
  b:2
};

// proxy只监听
class Obseervables{
  // 逻辑
  constructor(o){
    console.log(o);
    this._hander = {
      set(target,key,value,receiver){
        console.log(`检测到set的key为${key}发生变化`);
        return Reflect.set(target,key,value,receiver);
      },
    };
    return new Proxy(this._observables(o),this._hander);
  }

  // 为每一项进行监听  返回值应该是对象或者数组
  _observables(target){
    // 将每一层都监听到
    // 递归
    for (const key in target) { // target: 
      if(typeof target[key] === 'object'   && target[key]!==null){
        // 引用 需要递归调用
        this._observables(target[key]); // o.a  : [1,2],
        // 转换proxy才能监听到 
        target[key] = new Proxy(target[key],this._hander);
      }
    }
    return target;
  }
}

const ob = new Obseervables(o);
// ob 就是proxy实例
ob.a.push(3); // 检测到 push变化
// ob.c.a = 2; // 检测到变化

// vue3 proxy 底层